/*
 * Copyright (c) 2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.libermundi.theorcs.security.tapestry.components;

import org.apache.tapestry5.Asset;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.annotations.AfterRender;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.annotations.SessionAttribute;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.corelib.components.Any;
import org.apache.tapestry5.corelib.components.Checkbox;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.libermundi.theorcs.core.exceptions.ValueNotFoundException;
import org.libermundi.theorcs.core.tapestry.services.AppHelper;
import org.libermundi.theorcs.core.tapestry.services.configuration.ApplicationConfig;
import org.libermundi.theorcs.core.util.JsonUtils;
import org.libermundi.theorcs.security.SecurityConstants;
import org.libermundi.theorcs.security.exception.UserNotFoundException;
import org.libermundi.theorcs.security.model.User;
import org.libermundi.theorcs.security.services.UserManager;
import org.libermundi.theorcs.security.tapestry.pages.sns.JSGigya;
import org.libermundi.theorcs.security.tapestry.services.GigyaServices;
import org.libermundi.theorcs.security.tapestry.services.SecurityHelper;
import org.slf4j.Logger;

import com.google.gson.JsonElement;

/**
 * @author Martin Papy
 *
 */
public class GigyaForm {
	public static final String GIGYA_LOGIN_EVENT="gigyaLogin";
	
	@Inject
	private Logger _logger;

	@Inject
	private JavaScriptSupport _jsSupport;	
	
	@Inject
	private ApplicationConfig _appConfig;
  
	@Inject
	private AppHelper _appHelper;
	
	@Inject
	private UserManager _userManager;	
	
	@Inject
	private SecurityHelper _securityHelper;
  
	@Inject
	@Path("${security.scripts}/gigya.js")
	private Asset _gigyaJs;
	
	@Inject
	private GigyaServices _gigyaServices;	
  
	@Property(write=false)
	private boolean _gigyaEnabled;
	
	@Inject
	private ComponentResources _resources;
	
	@SessionAttribute(SecurityConstants.SESSION_GIGYA_JSON)
	private JsonElement _gigyaJson;	
	
	@SessionAttribute(SecurityConstants.SESSION_REGISTERING_USER)
	private User _registeringUser;
	
	@Component
	private Any _gigyaLogin;
	
	@Component
	private Any _gigyaError;
	
	@Component
	private Checkbox _snsRememberMe;	
	
	private String _registrationPage;

	@SetupRender
	public void setupRender() {
	  _gigyaEnabled =_appConfig.getBoolean(SecurityConstants.GIGYA_ENABLED);
	  _registrationPage = _appConfig.getString(SecurityConstants.PAGE_REGISTRATION);
	  if(_gigyaEnabled) {
		  _jsSupport.importJavaScriptLibrary(_appConfig.getString(SecurityConstants.GIGYA_BASE_URL) + _appConfig.getString(SecurityConstants.GIGYA_API_KEY));
		  _jsSupport.importJavaScriptLibrary(_appHelper.getEventLink(JSGigya.class,JSGigya.GET_JS_EVENT).toAbsoluteURI());			  
		  _jsSupport.importJavaScriptLibrary(_gigyaJs);	  
	  }
	  if(_registeringUser == null) {
		  _registeringUser = _userManager.getUser();
	  }
	}
	
	@AfterRender
	void afterRender() {
		if(_appConfig.getBoolean(SecurityConstants.GIGYA_ENABLED)) {
			JSONObject gigyaLoginParams = new JSONObject();
			gigyaLoginParams.put("showTermsLink", Boolean.FALSE);
			gigyaLoginParams.put("hideGigyaLink", Boolean.TRUE);
			gigyaLoginParams.put("height", Integer.valueOf(110));
			gigyaLoginParams.put("width", Integer.valueOf(250));
			gigyaLoginParams.put("containerID", _gigyaLogin.getClientId());

			_jsSupport.addScript("gigya.services.socialize.showLoginUI(gigyaConf,"+gigyaLoginParams.toString(Boolean.TRUE)+");");
			
			Link link = _resources.createEventLink(GIGYA_LOGIN_EVENT);
			JSONObject parameters = new JSONObject();
			parameters.append("url", link.toAbsoluteURI(Boolean.TRUE));
			parameters.append("snsRemembeMeId", "#" + _snsRememberMe.getClientId());
			parameters.append("gigyaErrorId", "#" + _gigyaError.getClientId());
			_jsSupport.addInitializerCall("setupGigyaLoginCallbackConf", parameters);
		}
	}
	
	@OnEvent(value=GIGYA_LOGIN_EVENT)
	public Object onGigyaLogin(
			@RequestParameter("UID") String gigyaUid,
			@RequestParameter("signatureTimestamp") String timestamp,
			@RequestParameter("UIDSignature") String signature,
			@RequestParameter("rememberMe") boolean rememberMe,
			@RequestParameter("jsonUser") String jsonUser
			) {
		
		//Save the GigyaJSON in Session
		_gigyaJson =  JsonUtils.parse(jsonUser);
		
		//We need to check the Signature from Gigya and Check the existence of the User in the DB
		JSONObject result = new JSONObject();
		if(_gigyaServices.isSignatureValid(gigyaUid, timestamp, signature)) {
			//Let's try to authenticate
			try {
				_gigyaServices.authenticate(gigyaUid,rememberMe);
				_logger.info("Gigya loggin successfull.");
				result.append("result", "success");
			}  catch (UserNotFoundException e) {
				// In Case User does not Exists in Db, then we create directly a new user
				// Once done, we send a notification email with Login / Password for account merging in the future
				// The redirect to HomePage
				
				_logger.info("Gigya User was not found. Switching  to registration process.");
				User newUser = _userManager.getUser();
				
				String nickname;
				try {	
					nickname = JsonUtils.getKey(_gigyaJson, "nickname").replaceAll("\\s", "");
				} catch (ValueNotFoundException e1) {
					nickname = "";
				}
				
				String firstName;
				try {
					firstName = JsonUtils.getKey(_gigyaJson, "firstName");
				} catch (ValueNotFoundException e1) {
					firstName = "";
				}
				
				String lastName;
				try {
					lastName = JsonUtils.getKey(_gigyaJson, "lastName");
				} catch (ValueNotFoundException e1) {
					lastName = "";
				}
				
				String email;
				try {
					email = JsonUtils.getKey(_gigyaJson, "email");
				} catch (ValueNotFoundException e1) {
					email = "";
				}
				
				String avatar;
				try {
					avatar = JsonUtils.getKey(_gigyaJson, "photoURL");
				} catch (ValueNotFoundException e1) {
					avatar = "";
				}
				
				String thumbnail;
				try {
					thumbnail = JsonUtils.getKey(_gigyaJson, "thumbnailURL");
				} catch (ValueNotFoundException e1) {
					thumbnail = "";
				}
				
				if(!nickname.isEmpty()) {
					newUser.setUsername(nickname);
					newUser.setNickName(nickname);
				}
				
				if(!firstName.isEmpty()) {
					newUser.setFirstName(firstName);
				}

				if(!lastName.isEmpty()) {
					newUser.setLastName(lastName);
				}
				
				if(!email.isEmpty()) {
					newUser.setEmail(email);
				}
				
				if(!avatar.isEmpty()) {
					newUser.setAvatar(avatar);
				}
				
				if(!thumbnail.isEmpty()) {
					newUser.setThumbnail(thumbnail);
				}

				_registeringUser = newUser;
				
				return _registrationPage;
			}
		} else {
			result.append("result", "failure");
			result.append("errormsg", "Gigya Signature is Invalid");
			_logger.error("Gigya Signature is Invalid");
			_gigyaJson = null;
		}
		
		return result;
	}	
}
